package com.ruoyi.system.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.pdf.FileUtil;
import com.ruoyi.common.utils.pdf.WordUtil;
import com.ruoyi.system.domain.AppCreateJobBill;
import com.ruoyi.system.entity.AppJobExplanPdfPath;
import com.ruoyi.system.service.AppCreateJobBillService;
import com.ruoyi.system.service.AppJobExplanPdfPathService;
import com.ruoyi.system.service.PDFService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class PDFServiceImpl implements PDFService {
    @Value("#{${export.type}}")
    private Map<String, String> exportType;

    @Value("#{${export.config.value}}")
    private Map<String, String> exportTypeValue;

    @Resource
    private AppCreateJobBillService appCreateJobBillService;
    @Resource
    private AppJobExplanPdfPathService appJobExplanPdfPathService;


    @Override
    public AjaxResult fillPDFData(Integer id, HttpServletRequest request, HttpServletResponse response) {
        //根据id查询作业票信息;
        AppCreateJobBill appCreateJobBill = appCreateJobBillService.queryById(id);
        if (null == appCreateJobBill) {
            //return;
            return AjaxResult.error("未查询到作业票");
        }
        if (null == appCreateJobBill.getJobType()) {
            //return;
            return AjaxResult.error("作业票类型不能为空");
        }
        //根据作业票类型查询pdf路径
        AppJobExplanPdfPath appJobExplanPdfPath = appJobExplanPdfPathService.queryById(Integer.valueOf(appCreateJobBill.getJobType()));
        //参数转换
        Map<String, Object> dataMap = getDataMap(appCreateJobBill);
        exportJobHead(appCreateJobBill, dataMap);
        List<String> checkBoxList = checkboxConfig(appCreateJobBill.getJobType());
        if (MapUtil.isEmpty(dataMap)) {
            //return;
            return AjaxResult.error("作业票参数转换异常");
        }
        String templateDir = appJobExplanPdfPath.getValueBase();
        try {
            String pdfFilePath = WordUtil.word2pdf(templateDir, appJobExplanPdfPath.getName(), id + "", dataMap, checkBoxList);
            if (StringUtils.isBlank(pdfFilePath)) {
                //return;
                return AjaxResult.error("作业票参数转换异常");
            }
            log.info("pdf导出>>>pdfFilePath:{}", pdfFilePath);
            downFile(request, response, FileUtil.getFileNameSuffix(pdfFilePath), pdfFilePath);
        } catch (Exception e) {
            log.error("pdf导出异常", e);
            return AjaxResult.error("作业票参数转换异常");
        } finally {
            //删除文件
            String zyExportPath = FileUtil.getZyExportDir(WordUtil.EXPORT_DIR, id + "");
            FileUtil.delFileByPath(zyExportPath);
        }
        return AjaxResult.success();
    }

    /**
     * 将作业票pdf文件转换为base64编码字符串
     *
     * @return
     */
    @Override
    public String readJobPdfToBase64(AppCreateJobBill appCreateJobBill, AppJobExplanPdfPath appJobExplanPdfPath) {
        Map<String, Object> dataMap = getDataMap(appCreateJobBill);
        exportJobHead(appCreateJobBill, dataMap);
        List<String> checkBoxList = checkboxConfig(appCreateJobBill.getJobType());
        if (MapUtil.isEmpty(dataMap)) {
            return null;
        }
        String templateDir = appJobExplanPdfPath.getValueBase();
        try {
            String pdfFilePath = WordUtil.word2pdf(templateDir, appJobExplanPdfPath.getName(),
                    appCreateJobBill.getId() + "", dataMap, checkBoxList);
            if (StringUtils.isBlank(pdfFilePath)) {
                return null;
            }
            log.info("pdf导出>>>pdfFilePath:{}", pdfFilePath);
            return readPdfToBase64(pdfFilePath);
        } catch (Exception e) {
            log.error("pdf导出异常", e);
        } finally {
            //删除文件
            String zyExportPath = FileUtil.getZyExportDir(WordUtil.EXPORT_DIR,
                    appCreateJobBill.getId() + "");
            FileUtil.delFileByPath(zyExportPath);
        }

        return null;
    }

    /**
     * 读取PDF文件并转换为Base64编码字符串
     */
    private String readPdfToBase64(String filePath) throws IOException {
        // 读取文件字节
        byte[] pdfBytes = Files.readAllBytes(Paths.get(filePath));
        // 编码为Base64字符串
        return Base64.getEncoder().encodeToString(pdfBytes);
    }

    /**
     * 下载文件到浏览器
     *
     * @param request
     * @param response
     * @param filename 要下载的文件名
     * @param filePath 需要下载的文件对象
     * @throws IOException
     */
    private void downFile(HttpServletRequest request, HttpServletResponse response, String filename, String filePath) throws IOException, URISyntaxException {
        //log.info("fileName:{}", filename);
        File file = new File(filePath);

        //  文件存在才下载
        if (file.exists()) {
            OutputStream out = null;
            FileInputStream in = null;
            try {
                // 1.读取要下载的内容
                in = new FileInputStream(file);

                // 2. 告诉浏览器下载的方式以及一些设置
                // 解决文件名乱码问题，获取浏览器类型，转换对应文件名编码格式，IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码
                String agent = request.getHeader("user-agent");
                if (agent.contains("FireFox")) {
                    filename = new String(filename.getBytes("UTF-8"), "iso-8859-1");
                } else {
                    filename = URLEncoder.encode(filename, "UTF-8");
                }
                // 设置下载文件的mineType，告诉浏览器下载文件类型
                String mineType = request.getServletContext().getMimeType(filename);
                response.setContentType(mineType);
                // 设置一个响应头，无论是否被浏览器解析，都下载
                response.setHeader("Content-disposition", "attachment; filename=" + filename);
                // 将要下载的文件内容通过输出流写到浏览器
                out = response.getOutputStream();
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                WordUtil.close(in);
                WordUtil.close(out);
            }
        }
    }

    protected Map<String, Object> getDataMap(AppCreateJobBill appCreateJobBill) {
        return dhzyData(appCreateJobBill);
    }

    @SuppressWarnings("all")
    private Map<String, Object> dhzyData(AppCreateJobBill appCreateJobBill) {
        Map<String, Object> map = JSONObject.parseObject(appCreateJobBill.getContent());
        if (!MapUtils.isEmpty(map)) {
            if (!MapUtils.isEmpty(exportTypeValue)
                    && exportTypeValue.containsKey(appCreateJobBill.getJobType())) {

                String string = exportTypeValue.get(appCreateJobBill.getJobType());

                List<String> codeName = new ArrayList<>();
                if (string.contains(",")) {
                    String[] strings = string.split(",");
                    codeName.add(Arrays.toString(strings));
                } else {
                    codeName.add(string);
                }

                for (String var : codeName) {
                    boolean containsKey = map.containsKey(var);
                    if (!containsKey) {
                        map.put(var, "无");
                    }
                }
            }

            map.forEach((k, v) -> {
                if (v instanceof List) {
                    List<Object> objectList = (List<Object>) v;
                    if (CollectionUtils.isEmpty(objectList)) {
                        map.put(k, "无");
                    }
                } else if (v instanceof Object) {
                    String toString = v.toString();
                    if (StringUtils.isBlank(toString)) {
                        map.put(k, "无");
                    }
                }
            });
        }
        if (StringUtils.isBlank(appCreateJobBill.getChangeBillNumber())) {
            map.put("changeBillNumber", "无");
        } else {
            map.put("changeBillNumber", appCreateJobBill.getChangeBillNumber());
        }
        if (StringUtils.isBlank(appCreateJobBill.getSpecialNumber())) {
            map.put("specialNumber", "无");
        } else {
            map.put("specialNumber", appCreateJobBill.getSpecialNumber());
        }
        return map;
    }

    protected static List<String> checkboxConfig(String type) {
        return dhzyCheckList();
    }

    // 列出文本框变量
    private static List<String> dhzyCheckList() {
        List<String> checkBoxList = new ArrayList<>();
        checkBoxList.add("Grade");
        checkBoxList.add("zylx");
        checkBoxList.add("zyjb");
        checkBoxList.add("dhzyjb");
        checkBoxList.add("risk");
        checkBoxList.add("yesOrNo1");
        checkBoxList.add("yesOrNo2");
        checkBoxList.add("yesOrNo3");
        checkBoxList.add("yesOrNo4");
        checkBoxList.add("yesOrNo5");
        checkBoxList.add("yesOrNo6");
        checkBoxList.add("yesOrNo7");
        checkBoxList.add("yesOrNo8");
        checkBoxList.add("yesOrNo9");
        checkBoxList.add("yesOrNo10");
        checkBoxList.add("yesOrNo11");
        checkBoxList.add("yesOrNo12");
        checkBoxList.add("yesOrNo13");
        checkBoxList.add("yesOrNo14");
        checkBoxList.add("yesOrNo15");
        checkBoxList.add("yesOrNo16");
        checkBoxList.add("yesOrNo17");
        checkBoxList.add("yesOrNo18");
        checkBoxList.add("yesOrNo19");
        checkBoxList.add("yesOrNo20");
        checkBoxList.add("yesOrNo21");
        checkBoxList.add("yesOrNo22");
        checkBoxList.add("yesOrNo23");
        checkBoxList.add("yesOrNo24");
        checkBoxList.add("yesOrNo25");
        return checkBoxList;
    }

    @SuppressWarnings("all")
    private void exportJobHead(AppCreateJobBill appCreateJobBill, Map<String, Object> map) {
        log.info("配置表:{}", JSON.toJSONString(exportType));
        log.info("配置表 加 入参:{}", JSON.toJSONString(map));
        handleValueOfMap(map);
        if (exportType.containsKey(appCreateJobBill.getJobType())) {
            List<String> codeName = new ArrayList<>();
            String keyValue = exportType.get(appCreateJobBill.getJobType());
            if (keyValue.contains(",")) {
                codeName = Arrays.asList(keyValue.split(","));
            } else {
                codeName.add(keyValue);
            }

            for (String key : codeName) {
                if (map.get(key) instanceof List) {
                    List<Object> objectList = (List<Object>) map.get(key);
                    String value = "";
                    for (Object var : objectList) {
                        value += var + ",";
                    }
                    String substring = value.substring(0, value.length() - 1);
                    map.put(key, substring);
                }
            }

        }
        log.info("配置表 加 出参:{}", JSON.toJSONString(map));
    }


    public void handleValueOfMap(Map<String, Object> map) {
        if (MapUtils.isEmpty(map))  { return ; }

        Stream<String> filterKeys = Stream.of("dhfs", "qtaqcs");
        filterKeys.forEach(key -> {
            if (map.containsKey(key)) {
                if (map.get(key) instanceof List) {
                    List<Object> objectList = (List<Object>) map.get(key);
                    String value = "";
                    for (Object var : objectList) {
                        value += var + ",";
                    }
                    String substring = value.substring(0, value.length() - 1);
                    map.put(key, substring);
                }
            }
        });
    }

}
